package com.soft.line.service.impl;

import com.soft.line.auth.AuthConstant;
import com.soft.line.auth.Md5Util;
import com.soft.line.auth.StrUtil;
import com.soft.line.entity.*;
import com.soft.line.filter.GsonUtil;
import com.soft.line.filter.HttpRequestUtil;
import com.soft.line.filter.UserTokenDto;
import com.soft.line.mapper.*;
import com.soft.line.service.LoginService;
import com.soft.line.util.MP.AjaxResult;
import com.soft.line.util.MP.OpenIdUtil;
import com.soft.line.util.MP.SystemConstant;
import com.soft.line.util.encrypt.AesEncryptUtil;
import com.soft.line.util.exception.CommonResult;
import com.soft.line.util.exception.ResultData;
import com.soft.line.util.redis.RedisClient;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
import io.swagger.models.auth.In;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.codec.binary.Base64;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.nio.charset.StandardCharsets;
import java.util.*;
import java.util.stream.Collectors;

import static com.soft.line.filter.HttpRequestUtil.REDIS_SERVICE;

/**
 * @author wu.xueqiao on 2020/5/12.
 * @version 0.1
 */
@Slf4j
@Service
public class LoginServiceImpl implements LoginService {

    @Autowired
    private UserInfoMapper userInfoMapper;
    @Autowired
    private LasUserInfoMapper lasUserInfoMapper;
    @Autowired
    private LasDepartmentInfoMapper lasDepartmentInfoMapper;
    @Resource
    private RedisClient redisClient;
    @Autowired
    private RoleInfoMapper roleInfoMapper;
    @Autowired
    private MenuInfoMapper menuInfoMapper;
    @Autowired
    private ButtonInfoMapper buttonInfoMapper;
    @Override
    public CommonResult userLogin(Map<String, String> map) {

        String password = (String)map.get("password");
        password= AesEncryptUtil.encrypt(password,AuthConstant.PASSWORD_ENCRYPT_KEY);
        map.replace("password",password);
        System.out.println("password:"+(String)map.get("password"));
        // UserInfo userInfo= userInfoMapper.userLogin(map);
        LasUserInfo userInfo = lasUserInfoMapper.userLogin(map);
        if(userInfo!=null){
            UserInfoToken userInfoToken=new UserInfoToken();
            userInfoToken.setUserName(userInfo.getUserName());
            userInfoToken.setRoleId(userInfo.getRoleId());
            String roleName=roleInfoMapper.selectRoleName(userInfo.getRoleId());
            userInfoToken.setRoleName(roleName);
            //userInfoToken.setPhone(userInfo.getPhone());
            userInfoToken.setPhone(userInfo.getTelephone());
            userInfoToken.setId(userInfo.getId());
            userInfoToken.setPassword(userInfo.getPassword());
            UserTokenDto user=new UserTokenDto();
            user.setUserInfo(userInfoToken);
            String token=returnToken(user);
            user.setToken(token);
            if (token == null || "".equals(token)) {
                return CommonResult.failed("redis插入失败");
            }
            return CommonResult.success(user);
        }else{
            return CommonResult.failed("登录失败！");
        }
    }

    @Override
    public CommonResult loginOut() {
        UserTokenDto userTokenDto=HttpRequestUtil.getUserToken();
        String key=userTokenDto.getUserInfo().getUserName();
        boolean out=REDIS_SERVICE.del(key);
        if(out){
            return CommonResult.success("退出登录成功！");
        }else {
            return CommonResult.failed("退出登录失败！");
        }

    }



    private String returnToken(final UserTokenDto user) {
        if (redisClient.getKeyValue(user.getUserInfo().getUserName()) == null || "".equals(redisClient.getKeyValue(user.getUserInfo().getUserName()))) {
//            final Map<String, Object> claims = new HashMap<>();
//            claims.put("password", user.getUserInfo().getPassword());
//            claims.put("username", user.getUserInfo().getUserName());
//            claims.put("uuid", UUID.randomUUID().toString());
            //final String token = Jwts.builder().setClaims(claims)
            //  .signWith(SignatureAlgorithm.HS512, HttpRequestUtil.key).compact();

            String spliceStr;
            Long lifeTime=null;
            if (lifeTime == null) {
                spliceStr = "{}-{}-{}";
            } else {
                spliceStr = "{}-{}-{}-{}";
                lifeTime = System.currentTimeMillis() + lifeTime;
            }
            String tokenPlainText = AuthConstant.USER_TOKEN_PREFIX + StrUtil.spliceStr(spliceStr, user.getUserInfo().getId(),
                    user.getUserInfo().getUserName(), user.getUserInfo().getRoleName(), lifeTime);
            String base64Token = Base64.encodeBase64String(tokenPlainText.getBytes(StandardCharsets.UTF_8));
            String md5PlainText = base64Token + AuthConstant.SAFE_STRING;
            String token=base64Token + Md5Util.encodeMd5(md5PlainText).toUpperCase();
            user.setToken(token);
            System.out.println(token);
            if (!redisClient.setKeyValue(user.getUserInfo().getUserName(), GsonUtil.javabeanToJson(user),HttpRequestUtil.expire)) {
                return null;
            }
            return token;
        } else {
            redisClient.setKeyTimeout(user.getUserInfo().getUserName(), HttpRequestUtil.expire);
            return GsonUtil.jsonToJavaBean(redisClient.getKeyValue(user.getUserInfo().getUserName())).getToken();
        }
    }

    @Override
    public AjaxResult autoLogin(String code) {
        Map<String, Object> data=new HashMap<>();

        //获取openId
        String openId= OpenIdUtil.getOpenId(code);

        if (openId==null) {
            System.out.println("获取openId失败！");
            return AjaxResult.error("获取微信信息失败，请稍后再试！");
        }
        UserInfo userInfo  = userInfoMapper.getUserInfoByOpenId(openId);
        //用户已经绑定过openId 则签发token 以及返回userInfo
        if (userInfo!=null) {
            try {
                UserInfoToken userInfoToken=new UserInfoToken();
                userInfoToken.setUserName(userInfo.getUserName());
                userInfoToken.setRoleId(userInfo.getRoleId());
                userInfoToken.setPhone(userInfo.getPhone());
                userInfoToken.setId(userInfo.getId());
                userInfoToken.setPassword(userInfo.getPassword());
                UserTokenDto user=new UserTokenDto();
                user.setUserInfo(userInfoToken);
                String token=returnToken(user);
                userInfo.setPassword("");
                data.put("userInfo", userInfo);
                data.put("token", token);
            } catch (Exception e) {
                e.printStackTrace();
                log.error("签发token失败！", e);
                return AjaxResult.error("登录失败，请稍后再试！");
            }

            return AjaxResult.success(data);

        }
        //用户未绑定过openId
        else {
            //返回未绑定
            return AjaxResult.noBand();
        }
    }

    @Override
    public AjaxResult bindUserInfo(Map<String, String> map) {
        String code = map.get("code");
        String phone = map.get("phone");
        String userName = map.get("userName");
        String password = map.get("password");
        Map<String, Object> data=new HashMap<>();
        UserInfo userInfo= userInfoMapper.getUserInfoByPhoneAndUserNameAndPassword(phone, userName, password);
        if (userInfo==null) {
            return AjaxResult.error("手机或账号密码错误！");
        }
        //获取openId
        String openId=OpenIdUtil.getOpenId(code);

        if (openId==null) {
            System.out.println("获取openId失败！");
            return AjaxResult.error("获取微信信息失败，请稍后再试！");
        }
        //绑定openId
        userInfoMapper.updateOpenIdById(openId, userInfo.getId());
        try {
            UserInfoToken userInfoToken=new UserInfoToken();
            userInfoToken.setUserName(userInfo.getUserName());
            userInfoToken.setRoleId(userInfo.getRoleId());
            userInfoToken.setPhone(userInfo.getPhone());
            userInfoToken.setId(userInfo.getId());
            userInfoToken.setPassword(userInfo.getPassword());
            UserTokenDto user=new UserTokenDto();
            user.setUserInfo(userInfoToken);
            String token=returnToken(user);
            userInfo.setPassword("");
            data.put("userInfo", userInfo);
            data.put("token", token);
        } catch (Exception e) {
            e.printStackTrace();
            log.error("签发token失败！", e);
            return AjaxResult.error("登录失败，请稍后再试！");
        }
        return AjaxResult.success(data);
    }

    @Override
    @Transactional(rollbackFor=Exception.class)
    public AjaxResult getUserInfo(Map<String, String> map) {
        UserTokenDto userTokenDto= HttpRequestUtil.getUserToken();
        int id=userTokenDto.getUserInfo().getId();
        String code=map.get("code");
        //获取openId
        String openId=OpenIdUtil.getOpenId(code);
        if (openId==null) {
            System.out.println("获取openId失败！");
            return AjaxResult.error("获取微信信息失败，请稍后再试！");
        }
        UserInfo userInfo  = userInfoMapper.getUserInfoByOpenId(openId);
        //有token又没有根据此openId查出用户 说明openId变了 此时根据用户id查询绑定用户openId
        if(userInfo==null) {
            userInfoMapper.updateOpenIdById(openId, id);
            userInfo  = userInfoMapper.getUserInfoByOpenId(openId);
            return AjaxResult.success(userInfo);
        }
        return AjaxResult.success(userInfo);
    }

    @Override
    public AjaxResult updatePassword(Map<String, Object> map) {
        UserTokenDto userTokenDto= HttpRequestUtil.getUserToken();
        int id=userTokenDto.getUserInfo().getId();

        int result=userInfoMapper.updatePassword(id,(String) map.get("password"));
        if(result>0){
            return AjaxResult.success();
        }
        return AjaxResult.error();
    }

    @Override
    public AjaxResult untie() {
        UserTokenDto userTokenDto= HttpRequestUtil.getUserToken();
        int id=userTokenDto.getUserInfo().getId();
        int result=userInfoMapper.deleteOpenId(id);
        if(result>0){
            return AjaxResult.success();
        }
        return AjaxResult.error();
    }

    @Override
    public UserPermission getUserPermission() {
        UserTokenDto userTokenDto=HttpRequestUtil.getUserToken();
        Integer userId = userTokenDto.getUserInfo().getId();
        LasUserInfo userInfo=lasUserInfoMapper.selectByPrimaryKey(userId);
        UserPermission userPermission=new UserPermission();
        userPermission.setId(userId);
        userPermission.setPhone(userInfo.getTelephone());
        userPermission.setModifyTime(userInfo.getLastUpdateTime());
        userPermission.setRoleId(userInfo.getRoleId());
        userPermission.setUserName(userInfo.getUserName());
        userPermission.setStatus(userInfo.getUserStatus());
        //对应部门
        LasDepartmentInfo lasDepartmentInfo = getSupDep(userInfo.getDepId());
        LasDepartmentInfo supDep = lasDepartmentInfoMapper.selectSuperiorDepByDepId(lasDepartmentInfo.getId());
        userPermission.setDepInfo(supDep);
        //获取对应角色
        RoleInfo role = roleInfoMapper.selectByPrimaryKey(userInfo.getRoleId());
        userPermission.setRole(role);
        List<Map<String, Object>> menuList = new ArrayList<>();
        List<Integer> list=new ArrayList<>();
        for (RoleInfo roleInfo:roleInfoMapper.selectAll(role.getName())){
            for (MenuInfo menuInfo:menuInfoMapper.selectByRoleId(roleInfo.getId())){
                Map<String, Object> menuMap = new HashMap<>();
                menuMap.put("menuId",menuInfo.getId());
                menuMap.put("menuName",menuInfo.getMenuName());
                menuMap.put("menuUrl",menuInfo.getMenuUrl());
                menuMap.put("menuIcon",menuInfo.getMenuIcon());
                if(menuInfo.getpId()!=-1){
                    list.add(menuInfo.getpId());
                }
                List<ButtonInfo> buttonList=buttonInfoMapper.selectButtonsByRoleIdAndMenuId(roleInfo.getId(),menuInfo.getId());
                menuMap.put("buttonList",buttonList);
                menuList.add(menuMap);
            }
        }
        List<Integer> pList=list.stream().distinct().collect(Collectors.toList());
        for(Integer id:pList){
            menuList.add(menuInfoMapper.getParentMenu(id));
        }
        userPermission.setMenuList(menuList);
        return userPermission;
    }

    @Override
    public LasDepartmentInfo getSupDep(String depId) {
        LasDepartmentInfo lasDepartmentInfo = lasDepartmentInfoMapper.selectSupDepByDepId(depId);
        while (lasDepartmentInfo!=null && !lasDepartmentInfo.getSuperiorDepId().equals("0")){
            lasDepartmentInfo = getSupDep(lasDepartmentInfo.getId());
        }
        lasDepartmentInfo = lasDepartmentInfoMapper.selectSuperiorDepByDepId(depId);
        return lasDepartmentInfo;
    }


}
